<?php
/**
 * CHANGELOG
 *  - 0.4
 *  	- Added support for 1 level through relations
 *  - 0.3
 *  	- Fixed a bug that made the CDbCriteria ignore the relation criteria configuration
 *  - 0.2
 *  	- DynamicDataProvider now allows the user to configure criteria, sort and pagination objects
 *  - 0.1
 *  	- initial release
 */

/**
 * @desc This behavior lets a model return CActiveDataProviders for its relations
 *
 * @author Asgaroth[dot]Belem[at]gmail[dot]com
 * @version 0.4
 * @since Jan 13, 2011 - 5:40:48 PM
 */
class DynamicDataProviderBehavior extends CActiveRecordBehavior {
	/**
	 *
	 * Returns a CActiveDataProvider of a relation
	 * @param string $relation the relation
	 * @param array $config
	 */
	public function getDataProvider($relation, $config = array()) {
		$relations = $this->owner->relations();
		if(!isset($relations[$relation])){
			throw new CDbException(Yii::t('yii','{class} does not have relation "{name}".',
			array('{class}'=>get_class($this->owner), '{name}'=>$relation)));
		}
		$c = array();
		
		$criteria = isset($config["criteria"]) ? $config["criteria"]: null;

		list($type, $relatedModel, $foreignKey) = $relations[$relation];

		if(isset($relations[$relation]["through"])){
			$through = $relations[$relation]["through"];
			unset($relations[$relation]["through"]);

			if($criteria === null || is_array($criteria)){
				if(is_array($criteria)){
					$conf = $criteria;
				}else{
					$conf = array_slice($relations[$relation], 3, null, true);
				}
				$conf["class"] = "CDbCriteria";
				$criteria = Yii::createComponent($conf);
			}
				
			list($throughType, $throughModel, $throughForeignKey) = $relations[$through];
			$m = CActiveRecord::model($throughModel);
			$t = $m->tableName();
			
			$pk = $m->getTableSchema()->primaryKey;
			if(is_array($pk)){
				$pk = $pk[0];
				$criteria->join = "JOIN {$t} AS {$through} ON {$through}.{$pk} = t.{$foreignKey} ";
			}else{
				$criteria->join = "JOIN {$t} AS {$through} ON {$through}.{$foreignKey} = t.{$m->getTableSchema()->primaryKey} ";
			}
			$criteria->join .= "JOIN {$this->owner->tableName()} ON {$this->owner->tableName()}.{$this->owner->getTableSchema()->primaryKey} = {$through}.{$throughForeignKey}";
				
			$criteria->compare("{$through}.{$throughForeignKey}", $this->owner->{$this->owner->getTableSchema()->primaryKey});
		}else{
			if($criteria === null || is_array($criteria)){
				if(is_array($criteria)){
					$conf = $criteria;
				}else{
					$conf = array_slice($relations[$relation], 3, null, true);
				}
				$conf["class"] = "CDbCriteria";
				$criteria = Yii::createComponent($conf);
			}
			$criteria->compare("t.".$foreignKey, $this->owner->{$this->owner->getTableSchema()->primaryKey});
		}


		$config['criteria'] = $criteria;

		return new CActiveDataProvider($relatedModel, $config);
	}//getDataProvider
}